<script lang="ts" setup name="ResultReview">
import {HeaderData} from '@/components/dTable/dTable'
import pageContainer from '@/components/pageContainer.vue'
import dTablePromote from '@/components/dTable/dTablePromote.vue'
import dHeader from '@/components/dTable/dHeader.vue'
import dIcon from '@/components/dIcon.vue'
import {reactive, ref, computed, onDeactivated, onActivated, watch} from 'vue'
import {OperButton, SearchButton, SearchFromItem} from '@/components/dTable/dHeader'
import {dayjs, ElMessage, FormRules} from 'element-plus/es'
import {getYearMonthDayStr, getYMDHMSStr, NotLeadingAndTrailingSpaces} from '@/util/common'
import {ColorRed, IconConfig, SeleteData} from '@/api/config'
import {
  auditRelease,
  getPrecisionResult,
  getResultReviewInfor,
  getResultReviewList,
  RegisterItemVOS,
  ResultReviewInforParams,
  ResultReviewList,
  ResultReviewParams,
  saveResult
} from '@/api/examinationManager/resultReview'
import {getInstrumentListReq} from '@/api/examinationManager/specimen'
import {Dayjs} from 'dayjs'
import useUser from '@/store/user'
const user = useUser.setup().store

//默认选中
const defualtSeleted = ref<ResultReviewList | undefined>(undefined)

// 左侧审核列表表单实例
const resultReviewTableRef = ref()

const instrumentList = ref<Array<SeleteData>>([])

// 选中的审核id
const resultReviewId = ref<string>('')

// 勾选的审核列表id
const selectionIdList = ref<Array<string>>([])
// 勾选数据
const selectionData = ref<Array<ResultReviewList>>([])

// 暂存结果列表
const stagingResultList = ref<Array<RegisterItemVOS>>([])

//体检医生id
const dutyDoctorId = ref<string>(user.userInfor?.id || '')
// 体检医生姓名
const dutyDoctorName = ref<string>(user.userInfor?.userName || '')

// 头部搜索表单
const searchFromItems = ref<Array<SearchFromItem>>([
  {
    label: '检验仪器',
    placeholder: '请选择检验仪器',
    type: 'selete',
    seleteData: instrumentList.value,
    prop: 'instrumentId',
    changeSubmit: true,
    notClearable: true,
    filterable: true
  },
  {
    label: '送检日期',
    placeholder: '请选择送检日期',
    type: 'antdDate',
    prop: 'sendTime',
    showTime: false,
    changeSubmit: true,
    notClearable: true,
    disabledDate: (current: Dayjs) => {
      return current && current > dayjs().endOf('day')
    },
    dateFormat: 'YYYY-MM-DD'
  },
  {
    label: '体检号',
    placeholder: '请输入体检号',
    type: 'input',
    prop: 'checkupNo',
    enterSubmit: true
  },
  {
    label: '姓名',
    placeholder: '请输入姓名',
    type: 'input',
    prop: 'personName',
    enterSubmit: true
  }
])

// 表单实例
const formRef = ref()

// 头部搜索表单规则
const searchFromRules = reactive<FormRules>({
  checkupNo: [
    {
      message: '长度应不超过20个字符',
      max: 20,
      trigger: ['change', 'blur']
    }
  ],
  personName: [
    {
      message: '长度应不超过20个字符',
      max: 20,
      trigger: ['change', 'blur']
    }
  ]
})

// 按钮搜索配置
const serachButtons = ref<Array<SearchButton>>([{type: 'search'}, {type: 'clear'}])

// 头部搜索数据
const searchFromData = reactive<ResultReviewParams>({
  instrumentId: '', // 仪器id
  instrumentSampleStatus: 2, //标本检验状态 检验结果审核页面使用，只能传2
  sendTime: getYearMonthDayStr(Date.now())
})

// 审核列表
const resultReviewTable = ref<Array<ResultReviewList>>([])
// 审核列表头
const resultReviewTableHeaderData = ref<Array<HeaderData>>([
  {
    prop: 'sampleNo',
    label: '标本号',
    columnType: 'text',
    align: 'left',
    width: '90'
  },
  {
    prop: 'checkupNo',
    label: '体检号',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'personName',
    label: '姓名',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'insSampleStatusName',
    label: '状态',
    columnType: 'slot',
    align: 'center',
    width: '120'
  }
])

// 审核表头按钮
const resultReviewButtons = ref<Array<OperButton>>([
  {
    label: '审核发布',
    type: 'noraml',
    iconConfig: {icon: 'common-audit-release', type: 'custom'},
    code: 'auditRelease'
  }
])

// 表格loading
const showResultReviewLoading = ref<boolean>(false)

// 审核项目
const resultReviewItemsTableHeaderData = ref<Array<HeaderData>>([
  {
    prop: 'enShortName',
    label: '项目英文简称',
    columnType: 'text',
    align: 'left',
    'min-width': '120'
  },
  {
    prop: 'itemName',
    label: '项目名称',
    columnType: 'text',
    align: 'left',
    'min-width': '120'
  },
  {
    prop: 'result',
    label: '结果',
    columnType: 'slot',
    align: 'left',
    width: '150'
  },
  {
    prop: 'unitName',
    label: '单位',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'tips',
    label: '提示',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'viewRange',
    label: '参考区间',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'inspectDoctorName',
    label: '检验者',
    columnType: 'text',
    align: 'left',
    'min-width': '100'
  },
  {
    prop: 'reportTime',
    label: '检验时间',
    columnType: 'text',
    align: 'left',
    'min-width': '150'
  }
])

// 审核项目表头按钮
const resultReviewItemsButtons = computed<Array<OperButton>>(() => {
  return [
    {
      label: '保存',
      type: 'noraml',
      iconConfig: {icon: 'common-save', type: 'custom'},
      code: 'save',
      disabled: !resultReviewId.value
    }
  ]
})
// 表格loading
const showResultReviewItemsLoading = ref<boolean>(false)

// 控制是否现在校验提示
const showErrorTips = ref<boolean>(true)
// 体检项目结果
const formData = reactive<{resultReviewItemsData: Array<RegisterItemVOS>}>({resultReviewItemsData: []})

// 错提示图标
const errorIcon: IconConfig = {
  icon: 'CircleCloseFilled',
  type: 'el',
  size: 16,
  color: ColorRed
}

const rules = computed<FormRules>(() => {
  return {
    result: [
      {
        message: '最多20个字符!',
        trigger: ['change', 'blur'],
        max: 20
      },
      {
        message: '首尾不能为空格!',
        pattern: NotLeadingAndTrailingSpaces,
        trigger: ['change', 'blur']
      }
    ]
  }
})

/**
 * @description: 勾选
 * @param {*} rows
 * @return {*}
 */
const onMultipleSelection = (rows: Array<ResultReviewList>) => {
  selectionData.value = rows
  selectionIdList.value = rows.map((item) => {
    return item.id
  })
}

// 清除勾选
const clearMultipleSelection = () => {
  selectionData.value = []
  selectionIdList.value = []
}

/**
 * @description: 选择行数据
 * @param {*} row
 * @return {*}
 */
const onResultReviewRowClick = (row: ResultReviewList) => {
  if (row) {
    showResultReviewItemsLoading.value = true
    resultReviewId.value = row.id
    const params: ResultReviewInforParams = {
      id: row.id,
      checkupRegisterId: row.checkupRegisterId,
      gender: row.gender,
      age: row.age
    }
    getResultReviewInfor(params)
      .then((res) => {
        const {data} = res.data || []
        formData.resultReviewItemsData = data.registerItemVOS || []
        // 暂时保存结果列表，用于后面的数据对比,深拷贝
        stagingResultList.value = JSON.parse(JSON.stringify(formData.resultReviewItemsData))
      })
      .catch((err) => {
        console.warn(err)
        resultReviewId.value = ''
        formData.resultReviewItemsData = []
      })
      .finally(() => {
        showResultReviewItemsLoading.value = false
      })
  } else {
    resultReviewId.value = ''
    formData.resultReviewItemsData = []
  }
}

/**
 * @description: 获取审核列表
 * @return {*}
 */
const getResultReview = () => {
  showResultReviewLoading.value = true
  const params = {...searchFromData}
  params.instrumentId ? params.instrumentId : delete params.instrumentId
  params.startSendTime = dayjs(searchFromData.sendTime).startOf('day').format('YYYY-MM-DD HH:mm:ss')
  params.endSendTime = dayjs(searchFromData.sendTime).endOf('day').format('YYYY-MM-DD HH:mm:ss')
  delete params.sendTime
  getResultReviewList(params)
    .then((res) => {
      resultReviewTable.value = res.data.data
      // 默认选择第一行显示右侧数据
      if (!resultReviewTable.value.length) {
        resultReviewId.value = ''
        formData.resultReviewItemsData = []
      } else {
        // 初始化默认选中第一行的id
        !resultReviewId.value && (resultReviewId.value = resultReviewTable.value[0]?.id)
      }
      // 找到选中行的坐标
      let rowIndex =
        resultReviewTable.value.findIndex((item) => {
          return item.id === resultReviewId.value
        }) || 0
      rowIndex === -1 && (rowIndex = 0) // 如果没找到选中第一行
      resultReviewTableRef.value?.setSeleted(resultReviewTable.value[rowIndex]) // 选中上次的行
    })
    .catch((err) => {
      console.warn(err)
    })
    .finally(() => {
      showResultReviewLoading.value = false
    })
}

/**
 * @description: 获取检验仪器
 * @return {*}
 */
const getInstrumentList = () => {
  instrumentList.value.length = 0
  getInstrumentListReq().then((res) => {
    const {data} = res.data
    data.length &&
      data.forEach((item) => {
        instrumentList.value.push({label: item.instrumentName, value: item.id || ''})
      })
    searchFromData.instrumentId = instrumentList.value[0]?.value ? `${instrumentList.value[0]?.value}` : undefined
    getResultReview()
  })
}

/**
 * @description: 头部表单查询
 * @return {*}
 */
const onSubmit = () => {
  getResultReview()
}

/**
 * @description: 头部表单清空
 * @return {*}
 */
const onFormClear = () => {
  searchFromData.sendTime = getYearMonthDayStr(Date.now()) // 默认当天时间
  searchFromData.instrumentId = instrumentList.value[0]?.value ? `${instrumentList.value[0]?.value}` : undefined // 默认第一个仪器
  resultReviewId.value = '' // 清空行选择Id
  getResultReview()
}

/**
 * @description: 审核发布
 * @param {*} name
 * @return {*}
 */
const onAuditRelease = (name: string) => {
  if (name === 'auditRelease') {
    if (selectionIdList.value.length) {
      auditRelease(selectionIdList.value).then(() => {
        ElMessage.success('审核成功！')
        resultReviewId.value = '' // 清空选择行
        clearMultipleSelection() // 清除勾选
        getResultReview()
      })
    } else {
      ElMessage.warning('请勾选数据!')
    }
  }
}

/**
 * @description: 数字结果参考区间获取提示
 * @param {*} result 结果值
 * @param {*} dangerRangeLow  危急范围低值
 * @param {*} dangerRangeHigh 危急范围高值
 * @param {*} normalRangeHigh 正常范围上限
 * @param {*} normalRangeLow 正常范围下限
 * @return {*}
 */
const getNumberTips = (result?: string | null, dangerRangeLow?: number | null, dangerRangeHigh?: number | null, normalRangeHigh?: number | null, normalRangeLow?: number | null) => {
  //检测结果低于低危值时显示提示：↓↓
  if (Number(result) < Number(dangerRangeLow) && result && dangerRangeLow) {
    return '↓↓'
  }
  //检测结果低于参考区间下限值时显示提示：↓
  else if (Number(result) >= Number(dangerRangeLow) && Number(result) < Number(normalRangeLow) && result && dangerRangeLow && normalRangeLow) {
    return '↓'
  }
  //检测结果低于参考区间下限值时显示提示：↓
  else if (Number(result) < Number(normalRangeLow) && result && !dangerRangeLow && normalRangeLow) {
    return '↓'
  }
  // 检测结果高于参考区间上限值时显示提示：↑
  else if (Number(result) > Number(normalRangeHigh) && Number(result) <= Number(dangerRangeHigh) && result && dangerRangeHigh && normalRangeHigh) {
    return '↑'
  }
  // 检测结果高于参考区间上限值时显示提示：↑
  else if (Number(result) > Number(normalRangeHigh) && result && !dangerRangeHigh && normalRangeHigh) {
    return '↑'
  }
  // 检测结果高于高危值时显示提示：↑↑
  else if (Number(result) > Number(dangerRangeHigh) && result && dangerRangeHigh) {
    return '↑↑'
  } else {
    return ''
  }
}

/**
 * @description: 根据参考值和参考区间计算提示信息
 * @param {*} data
 * @return {*}
 */
const calculationTips = (data: RegisterItemVOS) => {
  // 定量结果
  if (data.inspectResultType === 1) {
    const dangerRangeLow = data?.instrumentReferenceRangeVO?.dangerRangeLow // 危急范围低值
    const dangerRangeHigh = data?.instrumentReferenceRangeVO?.dangerRangeHigh // 危急范围高值
    const normalRangeHigh = data?.instrumentReferenceRangeVO?.normalRangeHigh // 正常范围上限
    const normalRangeLow = data?.instrumentReferenceRangeVO?.normalRangeLow // 正常范围下限
    const result = data?.result // 结果值
    return getNumberTips(result, dangerRangeLow, dangerRangeHigh, normalRangeHigh, normalRangeLow)
  }
  // 定性结果
  else if (data.inspectResultType === 2) {
    if (data?.instrumentReferenceRangeVO?.dangerPositive === 1 && data?.result && /阳|\+/g.test(data?.result)) {
      return '↑'
    } else {
      return ''
    }
  }
  // 半定性结果
  else if (data.inspectResultType === 3) {
    if (data?.result && /^\d+(\.\d+)?$/.test(data?.result)) {
      // 数字类型的参考区间
      const index = data?.instrumentReferenceRangeVOList?.findIndex((item) => {
        return item.resultType === '1'
      })
      const instrumentReferenceRangeVO = data?.instrumentReferenceRangeVOList?.[index]
      const dangerRangeLow = instrumentReferenceRangeVO?.dangerRangeLow // 危急范围低值
      const dangerRangeHigh = instrumentReferenceRangeVO?.dangerRangeHigh // 危急范围高值
      const normalRangeHigh = instrumentReferenceRangeVO?.normalRangeHigh // 正常范围上限
      const normalRangeLow = instrumentReferenceRangeVO?.normalRangeLow // 正常范围下限
      const result = data?.result // 结果值
      return getNumberTips(result, dangerRangeLow, dangerRangeHigh, normalRangeHigh, normalRangeLow)
    } else {
      // 文字类型的参考区间
      const index = data?.instrumentReferenceRangeVOList?.findIndex((item) => {
        return item.resultType === '2'
      })
      const instrumentReferenceRangeVO = data?.instrumentReferenceRangeVOList?.[index]
      if (instrumentReferenceRangeVO?.dangerPositive === 1 && data?.result && /阳|\+/g.test(data?.result)) {
        return '↑'
      } else {
        return ''
      }
    }
  } else {
    return ''
  }
}

/**
 * @description: 修改审核结果之后，体检医生和报告时间要改变
 * @return {*}
 */
const changeResultData = (): Array<Partial<RegisterItemVOS>> => {
  const registerItemVOS: Array<Partial<RegisterItemVOS>> = []
  let changeFlage = false // 判断数据是否改变了
  formData.resultReviewItemsData?.length &&
    formData.resultReviewItemsData.forEach((item) => {
      item.result = getPrecisionResult(item.result, item.precision) ? getPrecisionResult(item.result, item.precision)?.toString() : null
      const newItem = {
        id: item.id,
        result: item.result || null, // 结果
        tips: item.tips, // 提示
        viewRange: item.instrumentReferenceRangeVO?.viewRange || '', // 参考区间
        inspectDoctorId: item.inspectDoctorId, // 检验医师id
        inspectDoctorName: item.inspectDoctorName, // 检验医生姓名
        reportTime: item.reportTime, // 检验时间
        sampleTypeName: item.sampleTypeName // 标本类型
      }
      // 当前行数据和改变之前的数据比较，如果改变了结果
      stagingResultList.value.forEach((el) => {
        if (item.result !== el.result && item.id === el.id) {
          changeFlage = true // 表示数据被修改了
          newItem.inspectDoctorId = item.result ? dutyDoctorId.value : null // 当前行改为当前医生id
          newItem.inspectDoctorName = item.result ? dutyDoctorName.value : null // 当前行改为当前医生姓名
        }
      })
      registerItemVOS.push(newItem)
    })
  // 一行数据修改了，所有行都变为当前时间
  changeFlage &&
    registerItemVOS.forEach((item) => {
      item.reportTime = item.result ? getYMDHMSStr(Date.now()) : null
    })
  return registerItemVOS
}

/**
 * @description: 保存
 * @param {*} name
 * @return {*}
 */
const onSave = (name: string) => {
  if (name === 'save') {
    formRef.value &&
      formRef.value.validate((valid: boolean, fields) => {
        if (valid) {
          const papams = {
            id: resultReviewId.value, // 左侧id
            registerItemVOS: changeResultData() // 结果数据
          }
          saveResult(papams).then(() => {
            getResultReview()
            ElMessage.success('保存成功！')
          })
        } else {
          let arr: Array<number> = []
          // 表格校验不通过的Map
          Object.keys(fields).forEach((key) => {
            // 截取下标
            const indexString = key.substring(key.indexOf('.') + 1, key.lastIndexOf('.'))
            const index = Number(indexString) + 1
            arr.push(index)
          })
          arr = [...new Set(arr)] // 去重
          ElMessage.error(`表格第${arr.join('、')}行内容格式有误或未填写，请检查！`)
        }
      })
  }
}

watch(
  () => formData.resultReviewItemsData,
  () => {
    formData.resultReviewItemsData.forEach((item) => {
      // 半定性的时候根据结果值来取参考区间
      if (item?.inspectResultType === 3) {
        if (item?.result && /^\d+(\.\d+)?$/.test(item?.result)) {
          // 数字类型的参考区间
          const index = item?.instrumentReferenceRangeVOList?.findIndex((item) => {
            return item.resultType === '1'
          })
          const instrumentReferenceRangeVO = item?.instrumentReferenceRangeVOList?.[index]
          item.viewRange = instrumentReferenceRangeVO?.viewRange || item.instrumentReferenceRangeVO?.viewRange || ''
        } else {
          // 文字类型的参考区间
          const index = item?.instrumentReferenceRangeVOList?.findIndex((item) => {
            return item.resultType === '2'
          })
          const instrumentReferenceRangeVO = item?.instrumentReferenceRangeVOList?.[index]
          item.viewRange = instrumentReferenceRangeVO?.viewRange || ''
        }
      } else {
        item.viewRange = item.instrumentReferenceRangeVO?.viewRange || ''
      }
      // 计算提示信息
      item.tips = calculationTips(item)
    })
  },
  {
    deep: true
  }
)

onActivated(() => {
  showErrorTips.value = true
  getInstrumentList()
})

onDeactivated(() => {
  showErrorTips.value = false
})
</script>
<template>
  <page-container>
    <div class="d-common-flex-col d-common-full">
      <d-header
        :search-rules="searchFromRules"
        :search-form-data="searchFromData"
        :search-form-items="searchFromItems"
        :search-buttons="serachButtons"
        :search-from-justify="'flexStart'"
        :search-from-full="true"
        @form-submit="onSubmit"
        @form-clear="onFormClear"
      />
      <div class="result-review-box d-common-flex-full">
        <d-table-promote
          ref="resultReviewTableRef"
          :show-footer="false"
          :search-buttons="[]"
          :search-from-full="false"
          :oper-buttons="resultReviewButtons"
          :stripe="true"
          :table-data="resultReviewTable"
          :table-header-data="resultReviewTableHeaderData"
          :show-selection="true"
          :default-seleted="defualtSeleted"
          :show-loading="showResultReviewLoading"
          class="left-table"
          @row-click="onResultReviewRowClick"
          @multiple-selection="onMultipleSelection"
          @operation="onAuditRelease"
        >
          <template #insSampleStatusName="{row}">
            <span :style="{color: row.insSampleStatusName === '待审核' ? '#F08300' : '#EE5B70 '}">{{ row.insSampleStatusName }}</span>
          </template>
        </d-table-promote>
        <div class="result-review-space" />
        <el-form ref="formRef" :rules="rules" :model="formData" class="right-table">
          <d-table-promote
            :show-footer="false"
            :search-buttons="[]"
            :stripe="true"
            :table-data="formData.resultReviewItemsData"
            :oper-buttons="resultReviewItemsButtons"
            :table-header-data="resultReviewItemsTableHeaderData"
            :highlight-current-row="false"
            :show-loading="showResultReviewItemsLoading"
            @operation="onSave"
          >
            <template #result="scope">
              <el-form-item :prop="`resultReviewItemsData.${scope.index}.result`" :rules="rules.result" :inline-message="true">
                <el-input v-model="scope.row.result" placeholder="请输入结果" clearable class="d-common-flex-full" />
                <template #error="{error}">
                  <div>
                    <el-popover :visible="showErrorTips" :width="160" placement="right" popper-class="error-tip">
                      <d-icon :icon-config="errorIcon" />
                      {{ error }}
                      <template #reference>
                        <span />
                      </template>
                    </el-popover>
                  </div>
                </template>
              </el-form-item>
            </template>
          </d-table-promote>
        </el-form>
      </div>
    </div>
  </page-container>
</template>
<style lang="less" scoped>
:deep(.d-table-form) {
  margin-bottom: 0;
}
:deep(.d-table-header-buttons) {
  padding: 10px;
}

.result-review-box {
  border-top: 1px solid #e7e7e7;
}
.result-review-space {
  background: var(--d-color-grey-1);
  height: 100%;
  width: 6px;
}
.left-table {
  flex: 1;
  margin-right: 10px;
}
.right-table {
  flex: 1.8;
  margin-left: 10px;
}
</style>
<style lang="less">
.error-tip {
  i {
    margin-right: 5px;
  }
  .el-popper__arrow::before {
    background: #ffdbdb !important;
  }
  &.el-popover {
    display: flex;
    align-items: center;
    color: #e13848;
    background: #ffdbdb;
  }
}
</style>
